package com.android.samples.mediastore.hms.drive.operate

import android.content.Context
import android.util.Log
import com.huawei.cloud.services.drive.Drive
import com.huawei.cloud.services.drive.model.Change
import com.huawei.cloud.services.drive.model.Channel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext


/**
 * 华为云空间服务提供当文件发生变化时推送通知的能力，从而保持云端与本地文件同步。
 *
 * 使用Changes功能需要您的App可实时接收变化的Server服务器，
 * 该Server可以接收变化并将变化信息实时推送给相应的客户端，客户端接收消息后可以及时刷新变化。
 *
 * 关闭推送指定的Channel的变化通知，关闭后，该Channel不再收到文件变化通知。
 * 注意构造的Channel对象中的Id和resourceId与Changes中subscribe的Channel对象的Id和resourceId一致。
 */
class Changes(private val drive: Drive) {
    val TAG = "Changes"

    /**
     * 注册文件变化通知
     * @param context 上下文环境
     * @param id UUID或其他字符串，唯一标识channel
     */
    private suspend fun watchChanges(context: Context, id: String) {
        withContext(Dispatchers.IO) {
            try {
                val startCursor = drive.changes().startCursor.execute()
                val cursor = startCursor.startCursor
                val content = Channel().apply {
                    // id可以自定义，注意和channels.stop接口保持一致
                    this.id = id
                    // 固定web_hook
                    type = "web_hook"
                    // 提供开发者用于接收变化的Server服务器地址
                    url = "https://addr.xxx.com:8086/path/to/webhook"
                    expirationTime = System.currentTimeMillis() + 300 * 1000L
                }

                val channel: Channel = drive.changes().subscribe(cursor, content).execute()
                // 需要将channelToken回传给业务服务器Url
                val channelToken: String = channel.userToken
                context.getSharedPreferences("channel_config", Context.MODE_PRIVATE)
                    .edit()
                    .putString("startPageVersion", cursor)
                    .putString("resourceId", channel.resourceId)
                    .apply()
            } catch (e: Exception) {
                Log.e(TAG, "watchChanges error: $e")
            }
        }
    }

    /**
     * 获取文件变化
     *
     * @param cursor 之前调用Changes.Subscribe传入的cursor
     */
    private suspend fun getChangesList(cursor: String): List<Change?>? {
        return withContext(Dispatchers.IO) {
            var changes: List<Change?>? = null
            try {
                val listRequest = drive.changes().list(cursor)
                listRequest.fields = "*"
                val changeList = listRequest.execute()
                changes = changeList.changes
            } catch (e: java.lang.Exception) {
                Log.e(TAG, "doChangesList error: $e")
            }
            changes
        }
    }


    /**
     * 关闭指定的Channel
     * @param context 上下文环境
     * @param id UUID或其他字符串，唯一标识channel, 与subscribe接口的id保持一致
     */
    private suspend fun stopChannel(context: Context, id: String) {
        withContext(Dispatchers.IO) {
            try {
                val preferences =
                    context.getSharedPreferences("channel_config", Context.MODE_PRIVATE)
                val resourceId = preferences.getString("resourceId", "")
                val channel = Channel()
                channel.id = id
                channel.category = "api#channel"
                channel.resourceId = resourceId
                val stopReq = drive.channels().stop(channel)
                stopReq.execute()
            } catch (e: java.lang.Exception) {
                Log.e(TAG, "stopChannels error: $e")
            }
        }
    }

}